//
//  YCGalleryViewController.swift
//  YCCamera
//
//  Created by Billy on 2024/4/15.
//

import UIKit
import Photos

class YCGalleryViewController: UIViewController {

    // MARK: - Properties
    
    private var categories: [AlbumCategoryModel] = []
    private var fetchResults: [String: PHFetchResult<PHAsset>] = [:]
    private let imageManager = PHCachingImageManager()
    private let itemsPerRow: CGFloat = 3
    private let sectionInsets = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
    
    // 用于缓存的尺寸
    private var thumbnailSize: CGSize = .zero
    private var previousPreheatRect = CGRect.zero
    
    private var selectedCategoryId: String = "" {
        didSet {
            if oldValue != selectedCategoryId {
                updateCategorySelection()
            }
        }
    }
    
    private var initialSwipeX: CGFloat = 0
    private var currentPage: Int = 0
    
    // MARK: - UI Components
    
    private lazy var categoryCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        layout.minimumInteritemSpacing = 10
        layout.minimumLineSpacing = 10
        layout.sectionInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
        
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.backgroundColor = .black
        collectionView.showsHorizontalScrollIndicator = false
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.register(CategoryCell.self, forCellWithReuseIdentifier: "CategoryCell")
        return collectionView
    }()
    
    private lazy var photoCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        layout.minimumLineSpacing = 0
        layout.minimumInteritemSpacing = 1
        layout.sectionInset = .zero
        
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.backgroundColor = .black
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.isPagingEnabled = true
        collectionView.showsHorizontalScrollIndicator = false
        collectionView.register(PhotoGridCell.self, forCellWithReuseIdentifier: "PhotoGridCell")
        return collectionView
    }()
    
    // MARK: - Lifecycle Methods
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupNavigation()
        checkPhotoLibraryPermission()
        
        // 注册照片库变化观察者
        PHPhotoLibrary.shared().register(self)
        
        // 计算缩略图大小
        let scale = UIScreen.main.scale
        let cellSize = calculateItemSize()
        thumbnailSize = CGSize(width: cellSize.width * scale, height: cellSize.height * scale)
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        updateCachedAssets()
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        imageManager.stopCachingImagesForAllAssets()
    }
    
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        
        // 如果视图大小改变，重新计算缩略图大小
        let newSize = calculateItemSize()
        let scale = UIScreen.main.scale
        let newThumbnailSize = CGSize(width: newSize.width * scale, height: newSize.height * scale)
        
        if thumbnailSize != newThumbnailSize {
            thumbnailSize = newThumbnailSize
            imageManager.stopCachingImagesForAllAssets()
            photoCollectionView.reloadData()
        }
    }
    
    // MARK: - Setup Methods
    
    private func setupUI() {
        view.backgroundColor = .black
        
        // 添加分类集合视图
        view.addSubview(categoryCollectionView)
        categoryCollectionView.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide)
            make.left.right.equalToSuperview()
            make.height.equalTo(40)
        }
        
        // 添加照片集合视图
        view.addSubview(photoCollectionView)
        photoCollectionView.snp.makeConstraints { make in
            make.top.equalTo(categoryCollectionView.snp.bottom).offset(10)
            make.left.right.bottom.equalToSuperview()
        }
    }
    
    private func setupNavigation() {
        title = "相册"
        
        // 设置导航栏样式
        navigationController?.navigationBar.barStyle = .black
        navigationController?.navigationBar.tintColor = .white
        navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
        
        // 添加关闭按钮
        let closeButton = UIBarButtonItem(title: "关闭", style: .plain, target: self, action: #selector(closeButtonTapped))
        navigationItem.leftBarButtonItem = closeButton
    }
    
    // MARK: - Actions
    
    @objc private func closeButtonTapped() {
        dismiss(animated: true, completion: nil)
    }
    
    // MARK: - Photo Library Methods
    
    private func checkPhotoLibraryPermission() {
        let status = PHPhotoLibrary.authorizationStatus()
        
        switch status {
        case .authorized:
            fetchAllPhotos()
        case .notDetermined:
            PHPhotoLibrary.requestAuthorization { [weak self] status in
                if status == .authorized {
                    DispatchQueue.main.async {
                        self?.fetchAllPhotos()
                    }
                }
            }
        case .denied, .restricted:
            showPermissionAlert()
        case .limited:
            fetchAllPhotos()
        @unknown default:
            break
        }
    }
    
    private func fetchAllPhotos() {
        // 清空现有数据
        categories.removeAll()
        fetchResults.removeAll()
        
        // 创建一个临时数组存储所有相册
        var allAlbums: [AlbumCategoryModel] = []
        
        // 1. 获取"最近项目"智能相册
        let recentAlbum = createRecentAlbum()
        allAlbums.append(recentAlbum)
        
        // 2. 获取"个人收藏"智能相册
        let favoriteAlbum = createFavoriteAlbum()
        allAlbums.append(favoriteAlbum)
        
        // 3. 获取用户创建的相册
        let userAlbums = fetchUserAlbums()
        allAlbums.append(contentsOf: userAlbums)
        
        // 4. 获取其他常用的智能相册
        let smartAlbums = fetchSmartAlbums()
        allAlbums.append(contentsOf: smartAlbums)
        
        // 5. 筛选出有照片的相册并更新数量
        updateAlbumsPhotoCount(allAlbums)
        categories = allAlbums.filter { $0.count > 0 }
        
        // 如果没有相册，至少保留"最近项目"
        if categories.isEmpty && !allAlbums.isEmpty {
            categories = [allAlbums[0]]
        }
        
        // 默认选中第一个相册
        if let firstAlbum = categories.first {
            firstAlbum.isSelected = true
            selectedCategoryId = firstAlbum.id
        }
        
        // 刷新UI
        DispatchQueue.main.async { [weak self] in
            self?.photoCollectionView.reloadData()
            self?.categoryCollectionView.reloadData()
            
            // 默认选中第一个分类
            if !self!.categories.isEmpty {
                let indexPath = IndexPath(item: 0, section: 0)
                self?.categoryCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .top)
            }
        }
    }
    
    // 创建"最近项目"相册
    private func createRecentAlbum() -> AlbumCategoryModel {
        let recentAlbum = AlbumCategoryModel(
            title: "最近项目",
            id: "recent-photos",
            isSelected: true
        )
        return recentAlbum
    }
    
    // 创建"个人收藏"相册
    private func createFavoriteAlbum() -> AlbumCategoryModel {
        let favoriteAlbum = AlbumCategoryModel(
            title: "个人收藏",
            id: "favorite-photos"
        )
        favoriteAlbum.fetchOptions.predicate = NSPredicate(format: "favorite == YES")
        return favoriteAlbum
    }
    
    // 获取用户创建的相册
    private func fetchUserAlbums() -> [AlbumCategoryModel] {
        let userAlbumCollections = PHAssetCollection.fetchAssetCollections(
            with: .album,
            subtype: .any,
            options: nil
        )
        
        var userAlbums: [AlbumCategoryModel] = []
        userAlbumCollections.enumerateObjects { collection, index, _ in
            let album = AlbumCategoryModel(
                collection: collection,
                title: collection.localizedTitle ?? "未命名相册",
                id: collection.localIdentifier
            )
            userAlbums.append(album)
        }
        
        return userAlbums
    }
    
    // 获取其他智能相册
    private func fetchSmartAlbums() -> [AlbumCategoryModel] {
        // 定义需要获取的智能相册类型
        let smartAlbumTypes: [PHAssetCollectionSubtype] = [
            .smartAlbumSelfPortraits,    // 自拍
            .smartAlbumPanoramas,        // 全景照片
            .smartAlbumVideos,           // 视频
            .smartAlbumTimelapses,       // 延时摄影
            .smartAlbumLivePhotos,       // 实况照片
            .smartAlbumScreenshots,      // 截图
            .smartAlbumDepthEffect,      // 人像模式
            .smartAlbumBursts            // 连拍快照
        ]
        
        var smartAlbums: [AlbumCategoryModel] = []
        
        for subtype in smartAlbumTypes {
            let collection = PHAssetCollection.fetchAssetCollections(
                with: .smartAlbum,
                subtype: subtype,
                options: nil
            )
            
            if let smartAlbum = collection.firstObject {
                let album = AlbumCategoryModel(
                    collection: smartAlbum,
                    title: smartAlbum.localizedTitle ?? "智能相册",
                    id: smartAlbum.localIdentifier
                )
                smartAlbums.append(album)
            }
        }
        
        return smartAlbums
    }
    
    // 更新相册中的照片数量
    private func updateAlbumsPhotoCount(_ albums: [AlbumCategoryModel]) {
        for album in albums {
            let fetchOptions = album.fetchOptions
            let fetchResult: PHFetchResult<PHAsset>
            
            if album.id == "recent-photos" {
                // 最近项目特殊处理
                fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
            } else if album.id == "favorite-photos" {
                // 收藏特殊处理
                fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
            } else if let collection = album.collection {
                // 普通相册
                fetchResult = PHAsset.fetchAssets(in: collection, options: fetchOptions)
            } else {
                continue
            }
            
            // 保存fetchResult供后续使用
            fetchResults[album.id] = fetchResult
            album.count = fetchResult.count
        }
    }
    
    private func updateCategorySelection() {
        // 找到当前选中分类的索引
        if let index = categories.firstIndex(where: { $0.id == selectedCategoryId }) {
            let indexPath = IndexPath(item: index, section: 0)
            
            // 滚动到选中的分类
            categoryCollectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
            
            // 同步滚动照片网格
            photoCollectionView.scrollToItem(at: indexPath, at: .left, animated: true)
        }
    }
    
    private func showPermissionAlert() {
        let alert = UIAlertController(
            title: "无法访问相册",
            message: "请在设置中允许访问您的相册",
            preferredStyle: .alert
        )
        
        alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: nil))
        alert.addAction(UIAlertAction(title: "设置", style: .default) { _ in
            if let url = URL(string: UIApplication.openSettingsURLString) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }
        })
        
        present(alert, animated: true, completion: nil)
    }
    
    private func calculateItemSize() -> CGSize {
        let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
        let availableWidth = view.frame.width - paddingSpace
        let widthPerItem = availableWidth / itemsPerRow
        
        return CGSize(width: widthPerItem, height: widthPerItem)
    }
    
    // 更新缓存的资源
    private func updateCachedAssets() {
        guard isViewLoaded && view.window != nil else { return }
        
        // 可见区域
        let visibleRect = CGRect(origin: photoCollectionView.contentOffset, size: photoCollectionView.bounds.size)
        
        // 预加载区域（向前和向后扩展一屏）
        let preheatRect = visibleRect.insetBy(dx: 0, dy: -0.5 * visibleRect.height)
        
        // 只有当滚动距离足够大时才更新缓存
        let delta = abs(preheatRect.midY - previousPreheatRect.midY)
        guard delta > view.bounds.height / 3 else { return }
        
        // 获取当前可见的分类ID
        let currentPage = getCurrentPage() ?? 0
        if currentPage >= categories.count { return }
        
        let currentCategoryId = categories[currentPage].id
        guard let currentFetchResult = fetchResults[currentCategoryId] else { return }
        
        // 计算开始缓存和停止缓存的资源
        let (addedRects, removedRects) = differencesBetweenRects(previousPreheatRect, preheatRect)
        
        // 获取要缓存的资源
        var addedAssets: [PHAsset] = []
        var removedAssets: [PHAsset] = []
        
        // 处理当前分类的资源
        for rect in addedRects {
            let indexPaths = photoGridCellIndexPathsForElements(in: rect, currentPage: currentPage)
            for indexPath in indexPaths {
                if indexPath.item < currentFetchResult.count {
                    addedAssets.append(currentFetchResult.object(at: indexPath.item))
                }
            }
        }
        
        for rect in removedRects {
            let indexPaths = photoGridCellIndexPathsForElements(in: rect, currentPage: currentPage)
            for indexPath in indexPaths {
                if indexPath.item < currentFetchResult.count {
                    removedAssets.append(currentFetchResult.object(at: indexPath.item))
                }
            }
        }
        
        // 更新缓存
        imageManager.startCachingImages(for: addedAssets, targetSize: thumbnailSize, contentMode: .aspectFill, options: nil)
        imageManager.stopCachingImages(for: removedAssets, targetSize: thumbnailSize, contentMode: .aspectFill, options: nil)
        
        // 存储预热区域以便下次比较
        previousPreheatRect = preheatRect
    }
    
    // 辅助方法：为PhotoGridCell中的内容获取合适的索引路径
    private func photoGridCellIndexPathsForElements(in rect: CGRect, currentPage: Int) -> [IndexPath] {
        // 获取当前可见PhotoGridCell的内容区域
        let visibleCellFrame = CGRect(
            x: CGFloat(currentPage) * photoCollectionView.bounds.width,
            y: 0,
            width: photoCollectionView.bounds.width,
            height: photoCollectionView.bounds.height
        )
        
        // 将rect转换为PhotoGridCell内的坐标
        let adjustedRect = rect.offsetBy(dx: -visibleCellFrame.origin.x, dy: 0)
        
        // 获取显示在当前可见PhotoGridCell中的所有cell的布局信息
        if let photoGridCell = photoCollectionView.cellForItem(at: IndexPath(item: currentPage, section: 0)) as? PhotoGridCell {
            return photoGridCell.indexPathsForElements(in: adjustedRect)
        }
        return []
    }
    
    private func differencesBetweenRects(_ old: CGRect, _ new: CGRect) -> (added: [CGRect], removed: [CGRect]) {
        if old.intersects(new) {
            var added = [CGRect]()
            if new.maxY > old.maxY {
                added.append(CGRect(x: new.origin.x, y: old.maxY, width: new.width, height: new.maxY - old.maxY))
            }
            if old.minY > new.minY {
                added.append(CGRect(x: new.origin.x, y: new.minY, width: new.width, height: old.minY - new.minY))
            }
            
            var removed = [CGRect]()
            if old.maxY > new.maxY {
                removed.append(CGRect(x: old.origin.x, y: new.maxY, width: old.width, height: old.maxY - new.maxY))
            }
            if new.minY > old.minY {
                removed.append(CGRect(x: old.origin.x, y: old.minY, width: old.width, height: new.minY - old.minY))
            }
            
            return (added, removed)
        } else {
            return ([new], [old])
        }
    }
    
    // 更新指定分类的照片
    private func updateFetchResult(for categoryId: String) {
        if let category = categories.first(where: { $0.id == categoryId }) {
            let fetchOptions = category.fetchOptions
            let fetchResult: PHFetchResult<PHAsset>
            
            if category.id == "recent-photos" {
                fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
            } else if category.id == "favorite-photos" {
                fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
            } else if let collection = category.collection {
                fetchResult = PHAsset.fetchAssets(in: collection, options: fetchOptions)
            } else {
                return
            }
            
            fetchResults[category.id] = fetchResult
            category.count = fetchResult.count
        }
    }
}

// MARK: - PHPhotoLibraryChangeObserver

extension YCGalleryViewController: PHPhotoLibraryChangeObserver {
    func photoLibraryDidChange(_ changeInstance: PHChange) {
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            
            var needsReload = false
            
            // 1. 监听用户创建的相册集合变化
            let userAlbumCollections = PHAssetCollection.fetchAssetCollections(
                with: .album,
                subtype: .any,
                options: nil
            )
            if let collectionChanges = changeInstance.changeDetails(for: userAlbumCollections) {
                // 检查是否有任何相册集合的变化，包括数量变化和内容变化
                if collectionChanges.hasIncrementalChanges || 
                   collectionChanges.fetchResultBeforeChanges.count != collectionChanges.fetchResultAfterChanges.count {
                    needsReload = true
                }
            }
            
            // 2. 监听智能相册集合变化
            let smartAlbumCollections = PHAssetCollection.fetchAssetCollections(
                with: .smartAlbum,
                subtype: .any,
                options: nil
            )
            if let smartCollectionChanges = changeInstance.changeDetails(for: smartAlbumCollections) {
                if smartCollectionChanges.hasIncrementalChanges || 
                   smartCollectionChanges.fetchResultBeforeChanges.count != smartCollectionChanges.fetchResultAfterChanges.count {
                    needsReload = true
                }
            }
            
            // 3. 检查现有已加载的相册是否被删除
            if !needsReload {
                // 检查每个已加载相册是否还存在
                for category in self.categories {
                    // 跳过内置的特殊相册（"最近项目"和"个人收藏"）
                    if category.id == "recent-photos" || category.id == "favorite-photos" {
                        continue
                    }
                    
                    // 对于有关联 collection 的相册，检查它是否被删除
                    if let collection = category.collection {
                        // 尝试获取相册的最新状态
                        let existingCollection = PHAssetCollection.fetchAssetCollections(
                            withLocalIdentifiers: [collection.localIdentifier],
                            options: nil
                        )
                        
                        // 如果相册不再存在（count为0），标记需要重新加载
                        if existingCollection.count == 0 {
                            needsReload = true
                            break
                        }
                    }
                }
            }
            
            // 处理UI更新 - 只在相册合集变化时重新加载
            if needsReload {
                // 相册集合变化，重新获取所有相册
                self.fetchAllPhotos()
            }
        }
    }
    
    // 获取当前页面（保留此辅助方法）
    private func getCurrentPage() -> Int? {
        let visibleRect = CGRect(origin: photoCollectionView.contentOffset, size: photoCollectionView.bounds.size)
        let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
        guard let indexPath = photoCollectionView.indexPathForItem(at: visiblePoint) else {
            return nil
        }
        return indexPath.item
    }
}

// MARK: - UICollectionViewDataSource

extension YCGalleryViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return categories.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if collectionView == categoryCollectionView {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryCell", for: indexPath) as! CategoryCell
            let category = categories[indexPath.item]
            cell.configure(with: category)
            return cell
        } else {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoGridCell", for: indexPath) as! PhotoGridCell
            let category = categories[indexPath.item]
            if let fetchResult = fetchResults[category.id] {
                cell.prepareForReuse()
                cell.configure(with: fetchResult, imageManager: imageManager, thumbnailSize: thumbnailSize)
            }
            return cell
        }
    }
}

// MARK: - UICollectionViewDelegateFlowLayout

extension YCGalleryViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if collectionView == categoryCollectionView {
            let category = categories[indexPath.item]
            let title = category.title
            let width = title.size(withAttributes: [.font: UIFont.systemFont(ofSize: 14, weight: .medium)]).width + 32
            return CGSize(width: width, height: 34)
        } else {
            return collectionView.bounds.size
        }
    }
}

// MARK: - UICollectionViewDelegate

extension YCGalleryViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if collectionView == categoryCollectionView {
            // 更新所有分类的选中状态
            for i in 0..<categories.count {
                categories[i].isSelected = (i == indexPath.item)
            }
            
            let category = categories[indexPath.item]
            selectedCategoryId = category.id
            
            // 在切换分类时更新 fetchResult
            updateFetchResult(for: selectedCategoryId)
            
            categoryCollectionView.reloadData()
            
            // 滚动到对应的 PhotoGridCell
            photoCollectionView.scrollToItem(at: indexPath, at: .left, animated: true)
        }
    }
}

// MARK: - UIScrollViewDelegate

extension YCGalleryViewController: UIScrollViewDelegate {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        if scrollView == photoCollectionView {
            let page = Int(scrollView.contentOffset.x / scrollView.bounds.width)
            if page >= 0 && page < categories.count {
                // 更新所有分类的选中状态
                for i in 0..<categories.count {
                    categories[i].isSelected = (i == page)
                }
                
                selectedCategoryId = categories[page].id
                
                // 在滑动结束时更新当前分类的 fetchResult
                updateFetchResult(for: selectedCategoryId)
                
                categoryCollectionView.reloadData()
            }
        }
    }
}


// MARK: - CategoryCell

class CategoryCell: UICollectionViewCell {
    let titleLabel: UILabel = {
        let label = UILabel()
        label.font = .systemFont(ofSize: 14, weight: .medium)
        label.textAlignment = .center
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupUI() {
        contentView.backgroundColor = UIColor(white: 0.2, alpha: 1.0)
        layer.cornerRadius = 12
        clipsToBounds = true
        
        contentView.addSubview(titleLabel)
        titleLabel.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
    
    func configure(with category: AlbumCategoryModel) {
        titleLabel.text = category.title
        updateAppearance(isSelected: category.isSelected)
    }
    
    private func updateAppearance(isSelected: Bool) {
        if isSelected {
            contentView.backgroundColor = .white
            titleLabel.textColor = .black
            transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
        } else {
            contentView.backgroundColor = UIColor(white: 0.2, alpha: 1.0)
            titleLabel.textColor = .lightGray
            transform = .identity
        }
    }
}

// MARK: - UICollectionView Extension

extension UICollectionView {
    func indexPathsForElements(in rect: CGRect) -> [IndexPath] {
        let allLayoutAttributes = collectionViewLayout.layoutAttributesForElements(in: rect) ?? []
        return allLayoutAttributes.map { $0.indexPath }
    }
} 
